;#
;# convolve_asm.S
;#
;# Computes the LP residual.
;# 
;# Oded Rosen, 2011   
;#

	.text
	.globl Residu
	
	.arm
	
;#************************************************************************
;#
;#  FUNCTION: Residu 
;#
;#  PURPOSE:
;#     Computes the LP residual.
;#
;#  DESCRIPTION:
;#     The LP residual is computed by filtering the input
;#	   speech through the LP inverse filter A(z).
;#
;#************************************************************************/

	;# inputs / outputs:
	a			.req r0		;# (i)  : prediction coefficients, 16 bit array
    x			.req r1		;# (i)  : speech signal, 16 bit array
    y			.req r2		;# (o)  : residual signal, 16 bit array
    lg			.req r3		;# (i)  : size of filtering, 16 bit
	
	;# temp values:
	i			.req r4		;# 16 bit
	j			.req r5		;# 16 bit
	t			.req r5		;# 16 bit
	s			.req r6		;# 32 bit
	xij			.req r7		;# 16 bit
	aj			.req r8		;# 16 bit
	ij			.req r9		;# 16 bit
	yi			.req r10	;# 16 bit
	t2			.req r10	;# 16 bit
	jm			.req r11	;# 16 bit
	
	

Residu:

		;# Stack current values:
		PUSH		{r4-r11}		;# stack

		MOV			i,#0
r_i_loop:
		  	
       	LDRSH 		xij,[x,+i]		;# s = L_mult (x[i], a[0]);
       	LDRSH		aj,[a]			;# s = L_mult (x[i], a[0]);
       	SMULBB		s,aj,xij		;# s = L_mult (x[i], a[0]);
       	QADD		s,s,s			;# s = L_mult (x[i], a[0]);

		MOV			j,#2
		MOV			jm,#-4
		
r_j_loop:
		ADD			ij,i,jm
		LDR			aj,[a,+j]		;# s = L_mac (s, a[j], x[i - j]);
		LDR			xij,[x,+ij]		;# s = L_mac (s, a[j], x[i - j]);
		SMULBT 		t2,aj,xij		;# s = L_mac (s, a[j], x[i - j]);
		SMULTB 		aj,aj,xij		;# s = L_mac (s, a[j], x[i - j]);
		QDADD		s,s,t2			;# s = L_mac (s, a[j], x[i - j]);
		QDADD		s,s,aj			;# s = L_mac (s, a[j], x[i - j]);
			    
	    ADD			j,j,#4
		ADD			jm,jm,#-4
		CMP			j,#22
		BLT			r_j_loop
;# r_j_loop ends
		LSL			s,s,#3 			;# s = L_shl (s, 3);
		
		mov			t,#0x00008000	;# y[i] = round (s);
		adds 		yi,s,t			;# y[i] = round (s);
		lsrvc 		yi,#16 			;# y[i] = round (s);
		bvc 		r_str			;# y[i] = round (s); 	
				
		movcs 		yi,#0x80000000 	;# y[i] = round (s);
		mvncc 		yi,#0x80000000	;# y[i] = round (s);
		lsr 		yi,#16			;# y[i] = round (s);
r_str:
		
		STRH		yi,[y,+i]		;# y[i] = round (s); 
	        
		ADD			i,i,#2
		CMP			i,lg,LSL #1
		BLT			r_i_loop
;# r_i_loop ends
		
		;# Unstack values and return:
		POP			{r4-r11}		;# unstack
		BX			lr				;# return
